package edu.fiu.cis.personalize.server.berkDB;

import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.je.Database;
import com.sleepycat.je.Transaction;


public class BerkeleyDBTransaction<K, V>
{
	private BTransaction<K, V>	transaction;
	private String	name;

	public BerkeleyDBTransaction(String name,TupleBinding<K> keyBinding,
			TupleBinding<V> valBinding)
	{
		super();
		transaction = new DefaultBtransaction<K, V>(keyBinding, valBinding);
		this.name = name;
	}

	public void put(final K k, final V v) {
		new TransactionWrapper<V>() {

			@Override
			protected V perform(Transaction tx, Database database) {
				transaction.save(k, v, tx, database);
				return v;

			}
		}.process();
	}
	
	public String getName() {
		return name;
	}

	public V get(K k) {
		return transaction.lookup(null, k, BerkeleyDBConfigure.getDatabase(name));
	}

	abstract class TransactionWrapper<ValType>
	{
		public ValType process() {
			Transaction tx = null;
			try {
				if (BerkeleyDBConfigure.getEnvironment(name).getConfig().getTransactional()) {
					tx = BerkeleyDBConfigure.getEnvironment(name).beginTransaction(null,
						null);
				}
				ValType v = perform(tx, BerkeleyDBConfigure.getDatabase(name));
				if (tx != null) {
					tx.commit();
				}
				return v;
			} catch (Exception e) {
				System.out.println("Database error");
				e.printStackTrace();
				try {
					if (tx != null)
						tx.abort();
				} catch (Exception ignored) {

				}
				throw new RuntimeException(e);
			}
		}

		protected abstract ValType perform(Transaction tx, Database database);
	}

	public boolean remove(final K k) {
		return new TransactionWrapper<Boolean>() {

			@Override
			protected Boolean perform(Transaction tx, Database database) {
				return transaction.remove(k, tx, database);
			}
		}.process();
	}

}
